﻿using Dt261.jsonmodel;
using Dt261.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Dt261.db;
using Dt261.help;
using Dt261.jsonmodel;
using Dt261.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Panuon.UI.Silver;
using NAudio.Wave;
using System.Windows;

namespace Dt261.ViewModel
{
    class SpeechWindowViewModel : ViewModelBase
    {
        SpeechFileItemDb speechFileItemdb;
        SpebechItemDb speechItemdb;
        SpeechResultDb resultdb;
        SpeechResultEntryDb entrydb;
        int toneVlaue = 60;

        bool isYuTesting;
        bool isTesting;
        private ObservableCollection<SpeechFileItem> allResults;
        public ObservableCollection<SpeechFileItem> AllResults { get => allResults; set { Set(ref allResults, value); } }

        public MemberInfo person { get; set; }

        SpeechFileItem selectSpeechFileItem;
        SpeechItem selectSpeechItem;
        public RelayCommand playCommand { get; set; }

        public RelayCommand nextCommand { get; set; }
        public RelayCommand preCommand { get; set; }
        public RelayCommand startEndCommand { get; set; }


        public RelayCommand hearOKCommand { get; set; }
        public RelayCommand hearErrorCommand { get; set; }
        public SpeechWindowViewModel()
        {
            //getAudioType("单音节");
            //getAudioData();
            speechItemdb = new SpebechItemDb(dbconfig.DatabaseFilename);
            speechFileItemdb = new SpeechFileItemDb(dbconfig.DatabaseFilename);
            resultdb = new SpeechResultDb(dbconfig.DatabaseFilename);
             entrydb = new SpeechResultEntryDb(dbconfig.DatabaseFilename);

            playCommand = new RelayCommand(playWAV);
            startEndCommand = new RelayCommand(startEndPlay);
            preCommand = new RelayCommand(pre);
            nextCommand = new RelayCommand(next);

            hearOKCommand = new RelayCommand(hearOK);
            hearErrorCommand = new RelayCommand(hearError);

            IsSaveEnable = true;
        }

        AudioFileReader audioFileReader;
        WaveOut waveOutDevice;

        WaveFileWriter waveFileWriter;

        private Dictionary<string, bool> okdictory = new Dictionary<string, bool>();

        private Dictionary<int, Dictionary<string, bool>> okYudictory = new Dictionary<int, Dictionary<string, bool>>();

        private float shibielv;
        public float Shibielv
        {
            get => shibielv; set { shibielv = value; RaisePropertyChanged(); }
        }
        public void hearOK()
        {
            if (SelectSpeechFileItem == null)
                return;
            if (IsYuTesting)
            {
                //对了的占当前音量为key的个数大于50%

                Dictionary<string, bool> array;
                if (!okYudictory.ContainsKey(ToneVlaue))
                {
                    array = new Dictionary<string, bool>();
                    okYudictory.Add(ToneVlaue, array);
                }

                array = okYudictory[ToneVlaue];
                if (!array.ContainsKey(SelectSpeechFileItem.testExpression))
                {
                    array.Add(SelectSpeechFileItem.testExpression, true);

                    Shibielv = (float)array.Count() * 100 / (float)AllResults.Count();

                    if (Shibielv > 50)
                    {
                        //找到了，当前ToneValue就是识别阈值
                  
                        Notice.Show("言语识别阈测试结果" + ToneVlaue + "dB", "提示", 3, MessageBoxIcon.Success);

                        return;
                    }
                }


                ToneVlaue -= 5;
                next();
            }
            else
            {
         
                if (!okdictory.ContainsKey(SelectSpeechFileItem.testExpression))
                {
                    okdictory.Add(SelectSpeechFileItem.testExpression, true);
                    Shibielv =(float)okdictory.Count() * 100 / (float)AllResults.Count();

                }
                SelectSpeechFileItem.heard = true;
                int index = AllResults.IndexOf(SelectSpeechFileItem);
                if (index < AllResults.Count - 1)
                    next();
                else
                {
                    Notice.Show("测试完成.", "提示", 3, MessageBoxIcon.Success);
                }
            }


        }

        public void hearError()
        {
            if (IsYuTesting)
            {
                ToneVlaue += 10;
                next();
            }
            else
            {
                if (SelectSpeechFileItem == null)
                    return;

                if (okdictory.ContainsKey(SelectSpeechFileItem.testExpression))
                {
                    okdictory.Remove(SelectSpeechFileItem.testExpression);
                    Shibielv = (float)okdictory.Count() * 100 / (float)AllResults.Count();

                }
                SelectSpeechFileItem.heard = false;
                int index = AllResults.IndexOf(SelectSpeechFileItem);
                if (index < AllResults.Count - 1)
                    next();
                else
                {
                    Notice.Show("测试完成.", "提示", 3, MessageBoxIcon.Success);
                }
            }
   
        }
        public void next()
        {
            int index = AllResults.IndexOf(SelectSpeechFileItem);
            if(index < AllResults.Count -1)
            {
                SelectSpeechFileItem = AllResults[index + 1];
            }
            else
            {
                if(IsYuTesting)
                {
                    SelectSpeechFileItem = AllResults[0];
                }
                else

                    Notice.Show("已经是最后一条测试项.", "提示", 3, MessageBoxIcon.Success);
                //
            }
        }

        public void pre()
        {
            int index = AllResults.IndexOf(SelectSpeechFileItem);
            if (index > 0 && AllResults.Count > 0 )
            {
                SelectSpeechFileItem = AllResults[index - 1];
            }
            else
            {
                if (IsYuTesting)
                {
                    SelectSpeechFileItem = AllResults[AllResults.Count - 1];
                }
                else
                    Notice.Show("已经是第一条测试项.", "提示", 3, MessageBoxIcon.Success);
                //
            }
        }
        public void startEndPlay()
        {

            this.IsTesting = !this.IsTesting;

            TestButtonText = !isTesting ? "开始测试" : "完成测试";
                if (this.IsTesting)
            {
                okdictory.Clear();
                playWAV();
            }
            else
            {
                if (IsYuTesting)
                {
                    DMSkin.Core.Broadcast.PushBroadcast("CLOSEWINDOW", "SpeechWindowViewModel"); //("CLOSEWINDOW", (obj) =>

                }
                else
                {

                    if(AllResults == null || AllResults.Count() == 0)
                    {
                        return;
                    }
                    IsSaveEnable = false;
                    TestButtonText = "正在提交...";



                    //http.Request.Accept = HttpContentTypes.ApplicationJson;
                    //http.Request.ContentType = HttpContentTypes.ApplicationXWwwFormUrlEncoded;
#if true
                    try {

                    SpeechResultItem result = new SpeechResultItem();

                    result.ears = SpeechEarTypeSelect.Index;
                    result.spl = ToneVlaue;
                    result.result = (int)Shibielv;
                    result.id = System.Guid.NewGuid().ToString("N");

                   // long jan1st1970ms = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local).Ticks;
                        result.createTime = DateTime.Now;// (DateTime.Now.Ticks- jan1st1970ms)/10000;
                    result.testTable = speechItemSelect.testTable;
                    result.testTableType = speechItemSelect.testTableType;
                        result.personid = person.Uid;
                    //Content.Add("tableId", SpeechItemSelect.id);
                    //Content.Add("personId", person.Uid);


                        foreach (SpeechFileItem item in AllResults)

                    {

                        ResultDataListItem entry = new ResultDataListItem();

                        entry.resultId = result.id;
                        entry.id = System.Guid.NewGuid().ToString("N");
                        entry.testExpression = item.testExpression;
                        entry.pinyin = item.testPinyin;
                        entry.isCorrect = item.heard == false ? 0 : 1;
                        entry.isCorrectName = item.heard == false ? "错误" : "正确";


                        entrydb.AddSpeechResultEntry(entry);
                    }

                    resultdb.AddSpeechResult(result);

                        Notice.Show("言语测试结果已保存.", "提示", 3, MessageBoxIcon.Success);
                       
                        DMSkin.Core.Broadcast.PushBroadcast("NavigationBack2", "SpeechWindowViewModel");
                        DMSkin.Core.Broadcast.PushBroadcast("CLOSEWINDOW", "SpeechWindowViewModel"); //("CLOSEWINDOW", (obj) =>



                        return;

                    }
                    catch
                    {
                        IsSaveEnable = true;
                        TestButtonText = "完成测试";
                        Notice.Show("保存失败，请重试!.", "提示", 3, MessageBoxIcon.Error);
                        // this.Report = Http.errorWithJsonObject(o) + ",请重试!";
                    }

#else


                 var http = Http.SharedHttp();
                    Dictionary<string, object> Content = new Dictionary<string, object>();

               
                    List<Dictionary<string,string>> list = new List<Dictionary<string, string> > ();

                    foreach (SpeechFileItem  item in AllResults)

                    {
                        Dictionary<string, string> pContent = new Dictionary<string, string>();
                        pContent.Add("testExpression", item.testExpression);
                        pContent.Add("pinyin", item.testPinyin);
                        pContent.Add("isCorrect", item.heard == false?"0":"1");

                        list.Add(pContent);
                    }

                    ////Dictionary<int, int> rret = new Dictionary<int, int>();

                    //foreach (KeyValuePair<int, TestItem> kv in rightResult)

                    //{
                    //    Content.Add("right" + kv.Key + "hz", "" + kv.Value.Db);

                    //}
                    Content.Add("tableId", SpeechItemSelect.id);
                    Content.Add("personId", person.Uid);
                    Content.Add("spl", ToneVlaue);
                
                    Content.Add("ears", SpeechEarTypeSelect.Index);
                    Content.Add("result", (int)Shibielv);

                    Content.Add("li", list);

                    //Dictionary转json
                    string Contentjson = JsonConvert.SerializeObject(Content);


                    string ret = http.GetJSonResponse(Contentjson, Http.HOST + "tlyht/user/saveAudioResult", "post");

                    //var response = http.Post(, dict, HttpContentTypes.ApplicationXWwwFormUrlEncoded);
                    Console.WriteLine(ret);

                    if (ret != null)
                    {

                        JObject o = (JObject)JsonConvert.DeserializeObject(ret);

                        if (null == Http.errorWithJsonObject(o))
                        {
                            TestResultInfo info = JsonConvert.DeserializeObject<TestResultInfo>(o.ToString());

                          
                            Notice.Show("言语测试结果已保存.", "提示", 3, MessageBoxIcon.Success);
                            DMSkin.Core.Broadcast.PushBroadcast("UpdateHistory", "SpeechWindowViewModel");

                            DMSkin.Core.Broadcast.PushBroadcast("CLOSEWINDOW", "SpeechWindowViewModel"); //("CLOSEWINDOW", (obj) =>



                            return;
                        }
                        else
                        {
                            IsSaveEnable = true;
                            TestButtonText = "完成测试";
                            Notice.Show("保存失败，请重试!.", "提示", 3, MessageBoxIcon.Error);
                            // this.Report = Http.errorWithJsonObject(o) + ",请重试!";
                        }

                    }
                    else
                    {
                        IsSaveEnable = true;
                        TestButtonText = "完成测试";
                        Notice.Show("保存失败，请重试!.", "提示", 3, MessageBoxIcon.Error);
                        // this.Report = Http.errorWithJsonObject(o) + ",请重试!";
                    }
#endif


                }
            }
        }

            public void playWAV()
        {

            try
            {
                if (waveOutDevice != null)
                {
                    waveOutDevice.Stop();
                    waveOutDevice.Dispose();
                }

                if (SpeechItemSelect != null && SelectSpeechFileItem != null)
                {
                    waveOutDevice = new WaveOut();//
                    waveOutDevice.Volume = 1;
                    string url = Http.HOST
                        + SpeechItemSelect.fileUrl
                        + "/"
                        + SpeechItemSelect.pattern
                         + "/"
                        + SpeechItemSelect.folder
                         + "/"
                        + SelectSpeechFileItem.testFile
                         + ".wav";
                    string file = Http.HttpDownloadFile(url);
                    //fileUrl+pattern+folder+testFile+".wav"
                    string file2 = file + SpeechEarTypeSelect.Name;
                    // WaveFormat f = audioFileReader.WaveFormat;


                    if (SpeechEarTypeSelect.Name.Equals("左耳"))
                    {
                        using (var inAudio = new WaveFileReader(file))
                        {
                            //Calculate required byte[] buffer.
                            var buffer = new byte[2 * inAudio.Length];//Assume average will be constant for WAV format.
                            int index = 0;
                            do
                            {
                                var outFile = file2;
                                int bytesRead = 0;
                                int off = 0;
                                do
                                {
                                    bytesRead = inAudio.Read(buffer, 0 + off, 2);
                                    off += 4;
                                } while (bytesRead > 0 && bytesRead < buffer.Length && off < buffer.Length);
                                //Write new file
                                using (var waveWriter = new WaveFileWriter(outFile, new WaveFormat(inAudio.WaveFormat.SampleRate, 2)))
                                {
                                    waveWriter.Write(buffer, 0, buffer.Length);
                                }
                                index++;
                            } while (inAudio.Position < inAudio.Length);
                        }
                    }
                    else if (SpeechEarTypeSelect.Name.Equals("右耳"))
                    {
                        using (var inAudio = new WaveFileReader(file))
                        {
                            //Calculate required byte[] buffer.
                            var buffer = new byte[2 * inAudio.Length];//Assume average will be constant for WAV format.
                            int index = 0;
                            do
                            {
                                var outFile = file2;
                                int bytesRead = 0;
                                int off = 2;
                                do
                                {
                                    bytesRead = inAudio.Read(buffer, 0 + off, 2);
                                    off += 4;
                                } while (bytesRead > 0 && bytesRead < buffer.Length && off < buffer.Length);
                                //Write new file
                                using (var waveWriter = new WaveFileWriter(outFile, new WaveFormat(inAudio.WaveFormat.SampleRate, 2)))
                                {
                                    waveWriter.Write(buffer, 0, buffer.Length);
                                }
                                index++;
                            } while (inAudio.Position < inAudio.Length);
                        }
                    }
                    else
                    {
                        file2 = file;
                    }


                    // waveFileWriter = new WaveFileWriter(file, new WaveFormat(44100, 2));

                    waveOutDevice.Volume = (float)(ToneVlaue / 100.0);
                    audioFileReader = new AudioFileReader(file2);///传入数据地址
                    waveOutDevice.Init(audioFileReader);
                    waveOutDevice.Play();
                }
                {
                    //           private int sampleRate;
                    //private byte[] ByteArr;
                    //private MemoryStream ByteMem;
                    //ByteArr = null;
                    //ByteMem = null;
                    //ByteArr = File.ReadAllBytes(pathOfWav.Text);
                    //sampleRate = BitConverter.ToInt32(ByteArr, 24) * 2;
                    //Array.Copy(BitConverter.GetBytes(sampleRate), 0, ByteArr, 24, 4);
                    //ByteMem = new MemoryStream(ByteArr);
                }
            }
            catch
            {
                Notice.Show("发生异常错误，请退出重试！", "提示", 3, MessageBoxIcon.Error);
            }

        }


        private ObservableCollection<SpeechEarType> _SpeechEarTypeS = null;

        public ObservableCollection<SpeechEarType> SpeechEarTypeSource
        {
            get
            {
                if (this._SpeechEarTypeS == null)
                {
                    this._SpeechEarTypeS = new ObservableCollection<SpeechEarType>() {
                        new SpeechEarType() { Index = 0, Code = "01", Name = "双耳" },
                        new SpeechEarType() {  Index = 1, Code = "02", Name = "左耳"  },
                        new SpeechEarType() {  Index = 2, Code = "03", Name = "右耳"  }

                 };


                }
                return this._SpeechEarTypeS;
            }
            set
            {
                this._SpeechEarTypeS = value;
                RaisePropertyChanged();
            }
        }


        private SpeechEarType _SpeechEarTypeSelect;
        public SpeechEarType SpeechEarTypeSelect
        {
            get
            {
                if (this._SpeechEarTypeSelect == null)
                {
                    _SpeechEarTypeSelect = SpeechEarTypeSource[0];
                }
                return this._SpeechEarTypeSelect;
            }
            set
            {
                this._SpeechEarTypeSelect = value;
              
                RaisePropertyChanged();


            }
        }

        private ObservableCollection<SpeechType> _SpeechTypeS = null;

        public ObservableCollection<SpeechType> SpeechTypeSource
        {
            get
            {
                if (this._SpeechTypeS == null)
                {
                    this._SpeechTypeS = new ObservableCollection<SpeechType>() {
                        new SpeechType() { Index = 0, Code = "01", Name = "单音节" },
                        new SpeechType() {  Index = 1, Code = "02", Name = "双音节"  },
                        new SpeechType() {  Index = 2, Code = "03", Name = "语句"  }

                 };


                }
                return this._SpeechTypeS;
            }
            set
            {
                this._SpeechTypeS = value;
                RaisePropertyChanged();
            }
        }


        private SpeechType speechTypeeSelect;
        public SpeechType SpeechTypeSelect
        {
            get
            {
                if(this.speechTypeeSelect == null)
                {
                    SpeechTypeSelect = SpeechTypeSource[0];
                }
                return this.speechTypeeSelect;
            }
            set
            {
                this.speechTypeeSelect = value;
                getAudioType(speechTypeeSelect.Name);
                RaisePropertyChanged();

                
            }
        }

        private ObservableCollection<SpeechItem> _SpeechItemS = null;

        public ObservableCollection<SpeechItem> SpeechItemSource
        {
            get
            {
                if (this._SpeechItemS == null)
                {
                    //this._SpeechItemS = new ObservableCollection<SpeechItem>() {
                    //    new SpeechItem() { Index = 0, Code = "00", Name = "连续" },
                    //    new SpeechItem() { Index = 1, Code = "01", Name = "0.5秒" },
                    //    new SpeechItem() { Index = 2, Code = "02", Name = "1秒" },
                    //    new SpeechItem() {  Index = 3, Code = "04", Name = "2秒"  }
                    //    //@[@"连续",@"0.5秒",@"1秒",@"2秒"];
                    // };


                }
                return this._SpeechItemS;
            }
            set
            {
                this._SpeechItemS = value;
                RaisePropertyChanged();
            }
        }

        private SpeechItem speechItemSelect;
        public SpeechItem SpeechItemSelect
        {
            get
            {
                if (this.speechItemSelect == null && SpeechItemSource != null && SpeechItemSource.Count > 0)
                {
                    SpeechItemSelect = SpeechItemSource[0];
                }
                return this.speechItemSelect;
            }
            set
            {
                this.speechItemSelect = value;

                getAudioData();

                RaisePropertyChanged();


            }
        }

     
        public SpeechFileItem SelectSpeechFileItem
        {
            get => selectSpeechFileItem;
            set
            {

                selectSpeechFileItem = value;
                if(IsTesting) playWAV();
                RaisePropertyChanged();


            }
        }

        public int ToneVlaue { get => toneVlaue; set {
                if (value < 0 || value > 100)
                {

                }
                else
                {
                    toneVlaue = value;

                    if (IsYuTesting)
                    {
                        //对了的占当前音量为key的个数大于50%

                        Dictionary<string, bool> array;
                        if (!okYudictory.ContainsKey(ToneVlaue))
                        {
                            array = new Dictionary<string, bool>();
                            okYudictory.Add(ToneVlaue, array);
                        }

                        array = okYudictory[ToneVlaue];

                        if(array.ContainsKey(SelectSpeechFileItem.testExpression))
                            array.Remove(SelectSpeechFileItem.testExpression);
                        array.Add(SelectSpeechFileItem.testExpression, true);

                        Shibielv = (float)array.Count() * 100 / (float)AllResults.Count();
                    }
                }
                RaisePropertyChanged();
            }
        }

        public bool IsTesting { get => isTesting; set { isTesting = value; IsNotTesting = !isTesting; RaisePropertyChanged(); } }

        bool isSaveEnable;
        public bool IsSaveEnable
        {
            get => isSaveEnable; set { isSaveEnable = value;  RaisePropertyChanged(); }
        }
        public bool IsNotTesting
        {
            get => !isTesting;
            set {  RaisePropertyChanged(); }
        }

        
        public string TestButtonText { get => !isTesting ? "开始测试" : "完成测试"; set { RaisePropertyChanged(); } }

        public bool IsYuTesting { get => isYuTesting; set { isYuTesting = value; RaisePropertyChanged(); } }

        public void getAudioData()
        {
            var http = Http.SharedHttp();
            //http.Request.Accept = HttpContentTypes.ApplicationJson;
            //http.Request.ContentType = HttpContentTypes.ApplicationXWwwFormUrlEncoded;
            if(SpeechItemSelect != null)
            {
                string type = SpeechItemSelect.id;


                List<SpeechFileItem> items = speechFileItemdb.GetSpeechItemsByRoid(type).OrderBy(t => t.serialNo).ToList();


                //items.Sort((x, y) => (int)x.id.ToInt()  - (int) y.id.ToInt() );//升序



                Console.WriteLine(items.ToString());

                AllResults = new ObservableCollection<SpeechFileItem>(items);

                if (AllResults.Count() > 0)
                {
                    SelectSpeechFileItem = AllResults[0];
                }

                //var content = new FormUrlEncodedContent(new[]
                //{
                //new KeyValuePair<string, string>("audioTypeId",type )

                //});

                //string result = http.GetResponse(content, Http.HOST + "tlyht/user/getAudioData", "post");

                //if(null != result)
                //{
                //    Console.WriteLine(result);

                //    JObject o = (JObject)JsonConvert.DeserializeObject(result);

                //    if (null == Http.errorWithJsonObject(o))
                //    {
                //        IList<SpeechFileItem> items = new List<SpeechFileItem>();


                //        items = JsonConvert.DeserializeObject<IList<SpeechFileItem>>(o["Data"].ToString());


                //        Console.WriteLine(items.ToString());

                //        AllResults = new ObservableCollection<SpeechFileItem>(items);

                //        if(AllResults.Count() > 0)
                //        {
                //            SelectSpeechFileItem = AllResults[0];
                //        }

                //    }
                //    else
                //    {
                //        //this.Report = Http.errorWithJsonObject(o) + ",请重试!";
                //    }
                //}

            }

        }


        public void getAudioType(string type)
        {


            IList<SpeechItem> items = speechItemdb.GetSpeechItemsByType(type);

            Console.WriteLine(items.ToString());

  

            SpeechItemSource = new ObservableCollection<SpeechItem>(items);

            if (SpeechItemSource.Count > 0)
            {
                SpeechItemSelect = SpeechItemSource[0];
            }
            //var http = Http.SharedHttp();
            ////http.Request.Accept = HttpContentTypes.ApplicationJson;
            ////http.Request.ContentType = HttpContentTypes.ApplicationXWwwFormUrlEncoded;

            //var content = new FormUrlEncodedContent(new[]
            //{
            //    new KeyValuePair<string, string>("testTableType", type)

            //});


            //string result = http.GetResponse(content, Http.HOST + "tlyht/user/getAudioType","post");

            //if(null != result)
            //{
            //    Console.WriteLine(result);

            //    JObject o = (JObject)JsonConvert.DeserializeObject(result);

            //    if (null == Http.errorWithJsonObject(o))
            //    {

            //        IList<SpeechItem> items = new List<SpeechItem>();


            //        items = JsonConvert.DeserializeObject<IList<SpeechItem>>(o["Data"].ToString());


            //        Console.WriteLine(items.ToString());

            //        SpeechItemSource = new ObservableCollection<SpeechItem>(items);

            //        if (SpeechItemSource.Count > 0)
            //        {
            //            SpeechItemSelect = SpeechItemSource[0];
            //        }

            //    }
            //    else
            //    {
            //        //this.Report = Http.errorWithJsonObject(o) + ",请重试!";
            //    }
            //}

        }
    }


 
}
